#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <iostream>
#include <fstream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/text.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/features2d.hpp>

class ParallelExtracCSER: public cv::ParallelLoopBody
{
private:
    std::vector<cv::Mat> &channels;
    std::vector<std::vector<cv::text::ERStat>> &regions;
    std::vector<cv::Ptr<cv::text::ERFilter>> erFiter_1;
    std::vector<cv::Ptr<cv::text::ERFilter>> erFiter_2;
public:
    ParallelExtracCSER(std::vector<cv::Mat> &_channels, std::vector<std::vector<cv::text::ERStat>> &_regions,
                       std::vector<cv::Ptr<cv::text::ERFilter>> _erFiter_1, std::vector<cv::Ptr<cv::text::ERFilter>> _erFiter_2)
        : channels(_channels), regions(_regions), erFiter_1(_erFiter_1), erFiter_2(_erFiter_2){}
    virtual void operator()( const cv::Range &r) const CV_OVERRIDE
    {
        for(int c = r.start; c < r.end; c++)
        {
            erFiter_1[c]->run(channels[c], regions[c]);
            erFiter_2[c]->run(channels[c], regions[c]);
        }
    }
    ParallelExtracCSER & operator=(const ParallelExtracCSER &a);
};

template  <class T>
class ParallelOCR: public cv::ParallelLoopBody
{
private:
    std::vector<cv::Mat> &detections;
    std::vector<std::string> &outputs;
    std::vector<std::vector<cv::Rect> > &boxes;
    std::vector<std::vector<std::string> > &words;
    std::vector<std::vector<float> > &confidences;
    std::vector<cv::Ptr<T> > &ocrs;
public:
    ParallelOCR(std::vector<cv::Mat> &_detections, std::vector<std::string> &_outputs, std::vector< std::vector<cv::Rect> > &_boxes,
                std::vector< std::vector<std::string> > &_words, std::vector< std::vector<float> > &_confidences,
                std::vector< cv::Ptr<T> > &_ocrs):detections(_detections),outputs(_outputs),boxes(_boxes),words(_words),confidences(_confidences),ocrs(_ocrs)
    {}

    virtual void operator()(const cv::Range &r) const CV_OVERRIDE
    {
        for(int c=r.start; c < r.end; c++)
        {
            ocrs[c%ocrs.size()]->run(detections[c], outputs[c], &boxes[c], &words[c], &confidences[c], cv::text::OCR_LEVEL_WORD);
        }
    }
    ParallelOCR & operator=(const ParallelOCR &a);
};

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    void WindowInit();
    std::string sourcePath;
    QString currentActive;
    void showImage(cv::Mat &image);
    bool fileExists(const std::string &filename);
    void textboxDraw(cv::Mat src, std::vector<cv::Rect> &groups, std::vector<float> &probs, std::vector<int> &indexes);
    bool isRepetitive(const std::string &s);
    void erDraw(std::vector<cv::Mat> &channels, std::vector<std::vector<cv::text::ERStat>> &regions, std::vector<cv::Vec2i> group, cv::Mat segmentation);

public slots:
    void slot_importImage();
    void slot_saveImage();
    void slot_textDetector();
    void slot_textRecognizer();
};


#endif // MAINWINDOW_H
